import { Container } from "pixi.js";
import { TextInterpreter } from "@/utils/TextInterpreter.js";
import { Sprite_PlaneText } from "@/sprites/Sprite_PlaneText";

export class ScrollText extends Container {

    constructor(viewW, viewH) {
        super();

        this.viewW = viewW;
        this.viewH = viewH;

        this.canvas = document.createElement('canvas');
        this.context = this.canvas.getContext('2d');
        this.context.font = '28px GameFont';

        this._fontSize = 28;
        this._italic = false;

        this.active=false;

        /**
         * @type {Array}
         */
        this.root = [];
        /**
         * @type { Sprite_PlaneText[] }
         */
        this.scrollingPages = [];
        /**
         * @type { Sprite_PlaneText[] }
         */
        this.waitPages = [];

        this.gbCount=1800;

        Sprite_PlaneText.speed = Sprite_PlaneText.slowSpeed;
    }

    _setFontSize(size) {
        this._fontSize = size;
        this.context.font = `${size}px GameFont`;
    }

    makeFontBigger() {
        if (this._fontSize <= 96) {
            this._setFontSize(this._fontSize + 12);
        }
    }

    makeFontSmaller() {
        if (this._fontSize >= 24) {
            this._setFontSize(this._fontSize - 12);
        }
    }

    textWidth(text) {
        return this.context.measureText(text).width;
    }

    makeNewPage() {
        return {
            width: 0,
            height: 0,
            data: []
        }
    }
    /**
     * 
     * @param {string} text 
     */
    start(text) {
        let len = text.length
        let x = 0;
        let y = 0;
        let normalText = '';
        let width = 0;
        let iconSize = 32;

        let variableText = '';
        let crtVarIndex = 0;

        let maxLineHeight = 36;
        let root = [];
        let page = { width: 0, height: 0, data: [] };
        for (let i = 0; i < len; ++i) {
            let symbol = text[i];
            if (!variableText && symbol == '\\') {
                let state = TextInterpreter.parse(text, i);
                let params = [];
                if (!state.failed) {
                    if (normalText) {
                        page.data.push({
                            type: 'T',
                            params: [normalText, x - width, y, width, maxLineHeight]
                        });
                        normalText = '';
                        width = 0;
                    }
                    switch (state.type) {
                        case 'V':
                            variableText = String($gameVariables.value(TextInterpreter.DismantleVariables(state)));
                            crtVarIndex = 0;
                            break;
                        case 'C':
                            params.push(TextInterpreter.DismantleVariables(state)); break;
                        case 'I':
                            if (x + iconSize > this.viewW) {
                                x = 0;
                                y += maxLineHeight;
                                if (y > this.viewH - maxLineHeight) {
                                    page.width = this.viewW;
                                    page.height = y;
                                    root.push(page);
                                    //开页新的
                                    page = this.makeNewPage();
                                    x = 0;
                                    y = 0;
                                } else {
                                    //开行新的
                                    page.data.push({ type: '\n' });
                                }
                            }

                            params.push(TextInterpreter.DismantleVariables(state), iconSize, x, y);
                            x += iconSize;
                            break;
                        case '{':
                            this.makeFontBigger();
                            maxLineHeight = this._fontSize + 8;
                            break;
                        case '}':
                            this.makeFontSmaller();
                            if (x == 0) {
                                maxLineHeight = this._fontSize - 8;
                            }
                        default:
                            break;
                    }
                    if (state.type != 'V') {
                        page.data.push({
                            type: state.type,
                            params
                        });
                        params = [];
                    }

                    i = state.nexti;
                    continue;
                }
            }
            if (variableText) {
                symbol = variableText[crtVarIndex++];
                if (crtVarIndex >= variableText.length) {
                    crtVarIndex = 0;
                    variableText = '';
                }
                --i;
            }
            let charWidth = this.textWidth(symbol);
            if (x + charWidth > this.viewW) {
                if (normalText) {
                    page.data.push({
                        type: 'T',
                        params: [normalText, x - width, y, width, maxLineHeight]
                    });
                    normalText = '';
                    width = 0;
                }
                x = 0;
                y += maxLineHeight;
                if (y > this.viewH - maxLineHeight) {
                    page.width = this.viewW;
                    page.height = y;
                    root.push(page);
                    //开页新的
                    page = this.makeNewPage();
                    x = 0;
                    y = 0;
                } else {
                    page.data.push({ type: '\n' });
                }
            }
            x += charWidth;
            width += charWidth;
            normalText += symbol;
        }

        if (normalText) {
            page.data.push({
                type: 'T',
                params: [normalText, x - width, y, width, maxLineHeight]
            });
        }

        if (page.data.length > 0) {
            page.width = this.viewW;
            page.height = (y + maxLineHeight);
            root.push(page);
        }

        this.root = root;
        this.startScrollPage();
    }

    startScrollPage() {
        if (this.root.length) {
            let page = this.newPage();
            page.start(this.root.shift());
            page.visible = true;
            page.y = this.viewH;
            this.active=true;
        }
    }
    lastPage() {
        return this.scrollingPages[this.scrollingPages.length - 1];
    }
    firstPage() {
        return this.scrollingPages[0];
    }

    newPage() {
        let page = null;
        if (this.waitPages.length) {
            page = this.waitPages.shift();
        } else {
            page = new Sprite_PlaneText();
            this.addChild(page);
        }
        this.scrollingPages.push(page);
        return page;
    }

    update() {
        if(!this.active)return;
        for (let page of this.scrollingPages) {
            page.update();
        }
        if (this.scrollingPages.length) {
            let first = this.firstPage();
            if (!first.visible) {
                this.scrollingPages.shift();
                this.waitPages.push(first);
            }
        }
        if (this.root.length > 0) {
            let last = this.lastPage();
            if (last) {
                if (last.y + last.height <= 1.5 * this.viewH) {
                    let page = this.newPage();
                    page.start(this.root.shift());
                    page.y = last.y + last.height;
                    page.visible = true;
                }
            }else{
                this.startScrollPage();
            }
            this.gbCount=1800;
        }else if(this.waitPages.length>0){
            --this.gbCount;
            if(this.gbCount<=0){
                this.gbCount=1800;
                let page=this.waitPages.pop();
                page.destroy();
                this.removeChild(page);
            }
        }else{
            this.active=false;
        }
    }

    show(){
        this.active=false;
        this.visible=false;
    }

    hide(){
        this.active=true;
        this.visible=true;
    }
}